<?php
/**
 * Service_Image
 *
 * Класс для загрузки изображений
 *
 * @author Дмитрий Кузьма <kouzma.d@gmail.ru>
 * @version 3.1
 * 
 * Пока пропущены следующие действия:
 *  - удаление картинок при редактировании объекта
 *  - $watermark
 *  - сохранение картинок в ActiveRecord
 */
class Service_Image{

   static $maxImageSize = 2097152;//2097152;
   static $maxImageWidth = 4096; //2048;
   static $maxImageHeight = 4096;//2048;
   static $defaultQuality = 100;//100;

   private $_goalFolder; // Папка для сохранения изображения
   private $_goalName;   // Название файлабез расширения) для сохранения изображения
   private $_resizeType = false;  // Флаг того, каким образом сохранять изображение
   private $_allowEmpty = false;  // Флаг того, каким образом сохранять изображение
   private $_arrAvailableExtensions = array('jpg', 'gif', 'png'); // Массив допустимых расширений
   private $_arrSizes = array();
   private $_afterPrefixName = null; // Название файла после префикса
   private $_usePrefix = false; // Флаг того, следует ли использовать префикс
   
   // Информация по ресурсу
   private $_srcFile;   // Путь к исходному файлу
   private $_srcImage;  // Объект картинки, созданный из исходного файла
   private $_srcImagick;  // Объект Image Magick картинки, созданный из исходного файла
   private $_srcWidth;  // Ширрина исходного изображения
   private $_srcHeight; // Высота исходного изображения
   private $_imageType;        // Тип картинки (расширение)
   private $_isLoaded = false; // Флаг загружена ли картинка (готова ли она к сохранению)
   
   // Обработка ошибок и поддержка imageMagick
   private $_imageMagickSupport = false;
   private $_errorExists = false;
   private $_throwException = false;
   private $_unlinkFileAfterSave = true;
   
   private $_fieldNameOfHTML = '';  // HTML поле, в которое заполняется файл
   private $_objectOfDatabase = '';  // Объект БД к которому относится сохраняемое изображение 
  
  public function __construct($arrSettings = null) {
  	//if (class_exists('Imagick')) $this->_imageMagickSupport = true;
		//else $this->_imageMagickSupport = false;
  	$this->_imageMagickSupport = false;
  	if ($arrSettings) foreach ($arrSettings as $settingName => $settingValue) {
  		$this->_setSetting($settingName, $settingValue);
  	}
  }
  
  
  /**
   * 
   * Загружает в объект исходник картинки из массива $_FILES
   * @param array $arrFile
   */
  public function loadScrAsArray($arrFile)  {
    $this->_isLoaded = false;
  	// проверка на размер (килобайты) закачиваемо файла
  	if (($arrFile['error']) == 1 || $arrFile['size'] > self::$maxImageSize) $this->throwImageError('You upload too large file! The file must be no larger than  ' . (self::$maxImageSize/1024) . ' kilobytes.');    
  	// проверка если файл для закачки не выбран
    if (($arrFile['error']) == 4 ){
    	if ($this->_allowEmpty) return false;
    	else $this->throwImageError('File was not loaded. Perhaps, you didn\'t choose it');
    }
    
    // проверка на ошибку в процессе закачки файла
    if (($arrFile['error']) == 3 ) $this->throwImageError('An error occurred while downloading a file, try again !!!');
    
    if ($this->isErrorExists()) return false;
    // Проверка размера (ширина и высота) закачиваемого файла
    list($width, $height) = getimagesize($arrFile['tmp_name']);// получение размеров изображения
    if ( ($width > self::$maxImageWidth) || ($height > self::$maxImageWidth) ) {
      $this->throwImageError('You upload too large image! The image must be no more than ' . self::$maxImageWidth . ' to ' . self::$maxImageHeight .' px.');
    }

    // Сохраняем расширение файла
    $this->_setImageType($arrFile['type']);
    
    if ($this->isErrorExists()) return false;
    $this->_srcFile = $arrFile['tmp_name'];
    $this->_isLoaded = true;
    return true;
  }
  
  /**
   * 
   * Загружает в объект исходник картинки из файла
   * @param string $fullFilePath
   */
  public function loadScrAsFile($fullFilePath)  {
    $this->_isLoaded = false;
    if (empty($fullFilePath)) $this->throwImageError('You didn\'t send a file');
    //проверка на размер (килобайты) закачиваемо файла
    if ( filesize($fullFilePath) > self::$maxImageSize) $this->throwImageError('You upload too large file! The file must be no larger than  ' . (self::$maxImageSize/1024) . ' kilobytes.');
    
    //Проверка размера (ширина и высота) закачиваемого файла
    list($width, $height) = getimagesize($fullFilePath);
    if ( ($width > self::$maxImageWidth) || ($height > self::$maxImageWidth) ) $this->throwImageError('You upload too large image! The image must be no more than ' . self::$maxImageWidth . ' to ' . self::$maxImageHeight .' px.');
    
    if ($this->isErrorExists()) return false;
    $arrFileWords = explode('.', $fullFilePath);
    $this->_setImageTypeByExtension($arrFileWords[sizeof($arrFileWords) - 1]);
    if ($this->isErrorExists()) return false;
    $this->_srcFile = $fullFilePath;
    $this->_isLoaded = true;
    return true;
  }
  
  /**
   * 
   * Загружает в объект исходник картинки из POST массива
   * @param string $fileName
   */
  public function loadSrcAsRawPostData($fileName)  {
    $this->_isLoaded = false;
    if (empty($fileName)) $this->throwImageError('You didn\'t send a file');
  	
  	// Опредееляем промежуточные названия папок, расширений
    $arrFileName = preg_split('/\./', $fileName);
		$extension = strtolower($arrFileName[sizeof($arrFileName) - 1]);
		$tempFolder = IMAGES . 'temp/';
		
		// Определяем название файла для темпового сохранения
		do $tempFileName = md5(rand() + time());
	  while (is_file($tempFolder . $tempFileName . '.' . $extension));
	  $fullFilePath = $tempFolder . $tempFileName . '.' . $extension;
	
	  // Сохранение временного файла
	  $fp = fopen($fullFilePath, 'wb');
		fwrite($fp, $GLOBALS["HTTP_RAW_POST_DATA"]);
		fclose($fp);
		$this->_srcFile = $fullFilePath;
		
    //проверка на размер (килобайты) закачиваемо файла
    if ( filesize($fullFilePath) > self::$maxImageSize) {
    	unlink($fullFilePath);
    	$this->throwImageError('You upload too large file! The file must be no larger than  ' . (self::$maxImageSize/1024) . ' kilobytes.');
    }
    
    //Проверка размера (ширина и высота) закачиваемого файла
    list($width, $height) = getimagesize($fullFilePath);
    if ( ($width > self::$maxImageWidth) || ($height > self::$maxImageWidth) ) {
    	unlink($fullFilePath);
    	$this->throwImageError('You upload too large image! The image must be no more than ' . self::$maxImageWidth . ' to ' . self::$maxImageHeight .' px.');
    }
    
    if ($this->isErrorExists()) {
    	unlink($fullFilePath);
    	return false;
    }
    $arrFileWords = explode('.', $fullFilePath);
    $this->_setImageTypeByExtension($arrFileWords[sizeof($arrFileWords) - 1]);
    if ($this->isErrorExists()) {
    	unlink($fullFilePath);
    	return false;
    }
    
    $this->_isLoaded = true;
    return true;
  }
  

  

	/**
	 * Метод устанавливает свойство (поисковое)
	 *
	 * @param string $settingName
	 * @param mixed $settingValue
	 */
	private function _setSetting($settingName, $settingValue) {
		switch ($settingName) {
			case 'folder':
				$this->setGoalFolder($settingValue);
				break;
			case 'goalName':case 'name':
				$this->setGoalFolder($settingValue);
				break;
			case 'resizeType':
				$this->_resizeType = (bool)$settingValue;
				break;			
			case 'allowEmpty':
				$this->_allowEmpty = (bool)$settingValue;
				break;			
			case 'availableExtensions':
				$this->_arrAvailableExtensions = $settingValue;
				break;			
			case 'usePrefix':
				$this->_usePrefix = (bool)$settingValue;
				break;			
			case 'throw': case 'exception':
				$this->_throwException = (bool)$settingValue;
				break;
			case 'fieldName':
				$this->setFieldName($settingValue);
				break;
			case 'object':case 'obj':
				$this->setObject($settingValue);
				break;
			case 'sizes':
				$this->setArrSizes($settingValue);
				break;
			default:
				throw new Exception('You are trying to use invalid configuration (' . $settingName . '). The assume settings are: "sizes", "folder", "subFolder", "imageName"');
				break;
		}
	}

  /**
   * Устанавливаем целевую директорию для загрузки файлов
   *
   * @param string $folder
   */
  public function setGoalFolder($folder) {
    $this->_goalFolder = $folder;
  }

  /**
   * Устанавливаем целевое название файла
   *
   * @param string $goalName
   */
  public function setGoalName($goalName) {
    $this->_goalName = $goalName;
  }
  /**
   * 
   * Сохраняет название поле HTML формы
   * @param string $fieldName
   */
  public function setFieldName($fieldName) {
  	$this->_fieldNameOfHTML = $fieldName;
  }
  
  /**
   * 
   * Сохраняет Объект БД к которому относится сохраняемое изображение
   * @param string $fieldName
   */
  public function setObject(ActiveRecord $obj) {
  	$this->_objectOfDatabase = $obj;
  }
  
  /**
   * Устанавливаем, в какаих размерах должно быть сохранено изображение
   *
   * @param array $arrSizes
   */
  public function setArrSizes($arrSizes) {
    $this->_arrSizes = array();
  	foreach ($arrSizes as $row => $arrSize) {
  	  foreach ($arrSize as $key => $value) {
    		if (is_numeric($key)) {
    			switch ($key) {
    				case 0: $this->_arrSizes[$row]['width'] = $value; break;
	    			case 1: $this->_arrSizes[$row]['height'] = $value; break;
	    			case 2: $this->_arrSizes[$row]['alias'] = $value; break;
	    			case 3: $this->_arrSizes[$row]['is_strict'] = $value; break;
	    			case 4: $this->_arrSizes[$row]['quality'] = $value; break;
	    			case 5: $this->_arrSizes[$row]['is_main'] = $value; break;
	    			case 6: $this->_arrSizes[$row]['prefix'] = $value; break;
	    			default: break;
    			}
    		}
    		else $this->_arrSizes[$row][$key] = $value;
    	}
    }
  }
  
  /**
   * 
   * Получает ассоциативный массив размеров
   * @return array - ассоциативный массив размеров (если вызывается после сохранения, то содержит в том числе и названия папки и файла)
   */
  public function getArrSizes() {
  	return $this->_arrSizes;
  }
  
  /**
   * 
   * Возвращает массив с файлом и папкой основного изображения
   * @return array
   */
  public function getMainImageFolderAndFile() {
  	if (!$this->_arrSizes) return array(); 
  	foreach ($this->_arrSizes as $arrSize) {
  		if (isset($arrSize['is_main']) && $arrSize['is_main']) return array('pic_file' => $arrSize['pic_file'], 'pic_folder' => $arrSize['pic_folder']);
  	}
  	return array();
  }
  

  /**
   * 
   * Ошибка загрузки изображения
   * @param string $errText
   * @throws Exception
   */
  private function throwImageError($errText) {
    $this->_errorExists = true;
    if ($this->_unlinkFileAfterSave && is_file($this->_srcFile)) unlink($this->_srcFile); 	
    	
    // Автоматическое выбрасывание сообщений об ошибках в HTML-поле объекта БД
    //if (!empty($this->_fieldNameOfHTML)) {
    	//Exception_ActiveRecord::addFieldException($this->_fieldNameOfHTML, $errText);
    	//if (!empty($this->_objectOfDatabase)) Exception_ActiveRecord::addObjectException(get_class($this->_objectOfDatabase), $this->_fieldNameOfHTML, $errText);
    //}
    	
    //if ( $this->_throwException ) throw new Exception($errText);
  }
  
  /**
   * Проверяет, возникала ли ошибка
   *
   * @return boolean
   */
  public function isErrorExists() {
  	return $this->_errorExists;
  }
  
  /**
   * 
   * Устанавливает тип изображения
   * @param string $mimeType
   */
  private function _setImageType($mimeType) {
  	switch ($mimeType) {
      case 'image/jpeg': case 'image/pjpeg':
        $this->_imageType = 'jpg';
        break;
      case 'image/gif':
        $this->_imageType = 'gif';
        break;
      case 'image/x-png': case 'image/png':
        $this->_imageType = 'png';
        break;
      default: $this->throwImageError('This type of file is not supported.');
    }
    if (!in_array($this->_imageType, $this->_arrAvailableExtensions)) $this->throwImageError('This type of file is not supported.');
  }
  
/**
   * 
   * Устанавливает тип изображения по расширению файла
   * @param string $mimeType
   */
  private function _setImageTypeByExtension($ext) {
  	switch ($ext) {
      case 'jpeg': case 'jpg':
        $this->_imageType = 'jpg';
        break;
      case 'gif':
        $this->_imageType = 'gif';
        break;
      case 'png': 
        $this->_imageType = 'png';
        break;
      default: $this->throwImageError('This type of file is not supported.');
    }
    if (!in_array($this->_imageType, $this->_arrAvailableExtensions)) $this->throwImageError('This type of file is not supported.');
  
  }
  
  
  
  /**
   * 
   * Создает папки, если они не существуют
   */
  private function _createFoldersIfNotExist(){
  	if (empty($this->_goalFolder)) return false;
  	$arrFolders = explode('/', $this->_goalFolder);
  	$folderPath = IMAGES;
  	foreach ($arrFolders as $folderName) {
  		$folderPath .= $folderName . '/';
  		if (!is_dir($folderPath)) if (!mkdir($folderPath)) throw new Exception('Can not create a directory for uploads.');
  	}
  }
  
  /**
   * Метод сохраняет новый набор изображений
   *
   */
  public function save() {
  	$this->_createFoldersIfNotExist();
    list($this->_srcWidth, $this->_srcHeight) = getimagesize($this->_srcFile);// получение размеров изображения
    if (!$this->_imageMagickSupport) {
	    $this->_srcImage = $this->imageCreateFrom($this->_srcFile); 
	    if ( !$this->_srcImage ) throw new Exception('Error during opening image <br />');
    }
    else {
    	$this->_srcImagick = new Imagick($this->_srcFile);
    }
  	// Проверяем наличие размеров
    if (!$this->_arrSizes && !empty($this->_objectOfDatabase) && isset($this->_objectOfDatabase->arrImageSizes)) {
  		$this->setArrSizes($this->_objectOfDatabase->arrImageSizes);
  	}
  	if (!$this->_arrSizes) return false;  
  	if ($this->_usePrefix) $this->_generateNameAfterPrefixes();
   	foreach ($this->_arrSizes as $i => $arrSize) {
   		if(!$this->_usePrefix) $this->_arrSizes[$i]['pic_file'] = $this->_generateName();
   		else $this->_arrSizes[$i]['pic_file'] = $arrSize['prefix'] . $this->_afterPrefixName;
  		$this->_arrSizes[$i]['pic_folder'] = $this->_goalFolder;
  		if (!empty($arrSize['height']) && !empty($arrSize['width'])) $this->createImageFromFile($this->_arrSizes[$i]);
			else $this->saveExistingFile();
  	}
  	if (!$this->_imageMagickSupport) imagedestroy($this->_srcImage);
  	else $this->_srcImagick->destroy();
  	if ($this->_unlinkFileAfterSave) unlink($this->_srcFile);
  }
  
 /**
  * Метод  перемещает файл с изображением в нужную директорию
  * при необходимости метод создает соответствующие папки
  *
  */
  public  function saveExistingFile() {
    $this->_createFoldersIfNotExist();
  	if (!copy($this->_srcFile, IMAGES . $this->_goalFolder . $this->_generateName())) throw new Exception('Unable to copy uploaded file');
  }
  
  /**
   * 
   * Создает новое изображение из существующего в соответствии с номером размера
   * @param integer $sizeNumber - номер размера изображения
   * @throws Exception
   */
  public function createImageFromFile($arrSizeSettings) {
  	$resizeType = isset($arrSizeSettings['resize_type']) ? $arrSizeSettings['resize_type'] : null;
  	if (!in_array($resizeType, array('crop', 'save_propotion', 'no_propotions'))) $resizeType = 'save_propotion';
  	$quality = isset($arrSizeSettings['quality']) ? $arrSizeSettings['quality'] : self::$defaultQuality;
  	if (!$this->_imageMagickSupport) {
  		list($newWidth, $newHeight) = $this->getNewImageSizes($this->_srcWidth, $this->_srcHeight, $arrSizeSettings['width'], $arrSizeSettings['height'], $resizeType);// получение новых размеров изображения
	    list($src_x, $src_y, $cutWidth, $cutHeight) = $this->getCutImageCoords($this->_srcWidth, $this->_srcHeight, $newWidth, $newHeight);// получение прямоугольника для вырезания изображения
	    
	    if ($this->_imageType != 'png') {
	    	//создание нового изображения по размерам
			  $newImage = imagecreatetruecolor($newWidth, $newHeight);
			  if (!$newImage) throw new Exception('Error during creating image');
			  imagecopyresampled($newImage, $this->_srcImage, 0, 0, $src_x, $src_y, $newWidth, $newHeight, $cutWidth, $cutHeight);
			  if (! $this->imageSave($newImage, $arrSizeSettings['pic_file'], $quality)) throw new Exception('Could not save image with new dimensions');
	    }
	    else {
	    	// создание нового изображения по размерам
			  $newImage = self::imageResizeAlpha($this->_srcImage, $newWidth, $newHeight, $src_x, $src_y, $cutWidth, $cutHeight);
			  if (!$newImage) throw new Exception('Error during creating image');
			  if (!$this->imageSave($newImage, $arrSizeSettings['pic_file'])) throw new Exception('Could not save image with new dimensions');
	    }
	    imagedestroy($newImage);
  	}
  	else {
  		/* Create new imagick object */
      $newImage = $this->_srcImagick->clone();
  		switch ($resizeType) {
  			case 'crop':
  				$newImage->cropThumbnailImage($arrSizeSettings['width'], $arrSizeSettings['height']);
  				break;
  			case 'save_propotion':
  				$newImage->thumbnailImage($arrSizeSettings['width'], $arrSizeSettings['height'], true);
  				break;
  			case 'no_propotions':
  				$newImage->thumbnailImage($arrSizeSettings['width'], $arrSizeSettings['height']);
  				break;
  			default: throw new Exception('Unexpected type of picture compression');
  		}
  		$newImage->writeImage( IMAGES . $this->_goalFolder . $arrSizeSettings['pic_file'] );
  	}
  	
  }
  
  /**
	* Изменения размеров png с прозрачностью с учетом заданных размеров
	* с сохранением информации об альфа-каналах прозрачности
	*/
	private function imageResizeAlpha(&$src, $newWidth, $newHeight, $src_x = null, $src_y = null, $cutWidth = null, $cutHeight = null) {
		//Создаем новое изображение согласно ширине и высоте
		$newImage = imagecreatetruecolor($newWidth, $newHeight);

		//Создание нового прозрачного изображения
		$background = imagecolorallocate($newImage, 0, 0, 0);
		ImageColorTransparent($newImage, $background); //Создание нового полностью прозрачного изображения
		imagealphablending($newImage, false); // Отключаем альфа-смешение, чтобы сохранить альфа-канал (прозрачность)

		//Изменяем размеры png-файла
		imagecopyresampled($newImage, $src, 0, 0, $src_x, $src_y, $newWidth, $newHeight, $cutWidth, $cutHeight);
		return $newImage;
	}
  
  /**
   * Создает изображение соответствующего типа
   *
   * @param string $filePath
   */
  private function imageCreateFrom($filePath) {
    switch ($this->_imageType) {
      case 'jpg': return imagecreatefromjpeg($filePath);
      case 'gif': return imagecreatefromgif ($filePath);
      case 'png': return imagecreatefrompng($filePath);
      case 'bmp': return imagecreatefromwbmp($filePath);
      default: return false;
    }
  }
  
/**
   * вращает массив с размерами изображения согласно сжатию
   *
   * @param integer $widthSrc - ширина источника
   * @param integer $heightSrc - высота источника
   * @param integer $widthDist - ширина блока, в который впишется картинка
   * @param integer $heightDist - высота блока, в который впишется картинка
   * @param integer $resizeType - тип размеров (null/save_propotion/no_propotion/crop) - значение по умолчанию/с сохранением пропорций/без сохранения пропорций/с обрезанием краев
   * @return array
   */
  private function getNewImageSizes($widthSrc, $heightSrc, $widthDist, $heightDist, $resizeType = null) {
  	if ($resizeType === null) $resizeType = $this->_resizeType;
  	if (!in_array($resizeType, array('crop', 'save_propotion', 'no_propotions'))) $resizeType = 'save_propotion'; 
    $widthKoef = $widthSrc / $widthDist;
    $heightKoef = $heightSrc / $heightDist;
    
    if ($resizeType == 'crop' || $resizeType == 'no_propotions') { // Если обрезаем до строгих размеров (crop или без сохранения пропорций)
			if ($widthKoef >= 1 && $heightKoef >= 1) return array($widthDist, $heightDist);
			else {
				if ($widthKoef < 1 && $heightKoef < 1) return array($widthSrc, $heightSrc);
			  elseif ($widthKoef < 1) return array($widthSrc, $heightDist);
				else return array($widthDist, $heightSrc); // Загружаем очень маленькую картину
			}
    }
    elseif ($widthKoef >= 1 || $heightKoef >= 1) { // Если мы не обрезаем с сохранением пропорций. А размеры нужно уменьшать
    	if ( ($widthKoef <=1) && ($heightKoef <=1) ) return array($widthSrc, $heightSrc); // сжимать не требуется
    	if ($widthKoef > $heightKoef) return array(round($widthSrc/$widthKoef), round($heightSrc/$widthKoef)); // сжимаем в основном по ширине
	    else return array(round($widthSrc/$heightKoef), round($heightSrc/$heightKoef)); // сжимаем в основном по высоте
    }
    else return array($widthSrc, $heightSrc); // Загружаем очень маленькую картину
  }
  
/**
   * вращает массив с размерами изображения согласно сжатию
   *
   * @param integer $widthSrc - ширина источника
   * @param integer $heightSrc - высота источника
   * @param integer $widthDist - ширина блока, в который впишется картинка
   * @param integer $heightDist - высота блока, в который впишется картинка
   * @param integer $resizeType - тип размеров (null/save_propotion/no_propotion/crop) - значение по умолчанию/с сохранением пропорций/без сохранения пропорций/с обрезанием краев
   * @return array
   */
  private function getCutImageCoords($widthSrc, $heightSrc, $widthDist, $heightDist, $resizeType = null) {
  	if ($resizeType === null) $resizeType = $this->_resizeType;
  	if (!in_array($resizeType, array('crop', 'save_propotion', 'no_propotions'))) $resizeType = 'save_propotion';
  	$widthKoef = $widthSrc / $widthDist;
    $heightKoef = $heightSrc / $heightDist;
  	
    if ($resizeType != 'crop') { // Если мы не обрезаем до строгих размеров. А размеры нужно уменьшать
	    return array(0, 0, $widthSrc, $heightSrc);
    }
    else { // Если обрезаем до строгих размеров
      if ($widthKoef < 1 && $heightKoef < 1) return array(0, 0, $widthSrc, $heightSrc); // Если уменьшать не надо
      // Если надо уменьшать

      // Если по высоте обрезать не нужно
			$mainKoef = min($widthKoef, $heightKoef);
			$mainKoef = max($mainKoef, 1);

			$cutWidth = $mainKoef * $widthDist;
			$cutHeight = $mainKoef * $heightDist;

			$retWidth = ($widthSrc - $cutWidth) / 2;
			$retHeight = ($heightSrc - $cutHeight) / 2;

			return array($retWidth, $retHeight, $cutWidth, $cutHeight);
    }
  }
  
  /**
   * Сохраняет изображение на жесткий диск
   *
   * @param resource $image - объект изображения для сохранения
   * @param string $newFileName - название файла, в который будет сохранено изображений
   * @param integer $quality - качество сохранения изображения (только для jpg)
   * @return bool
   */
  private function imageSave($image, $newFileName, $quality = 100) {
  	$fullPath = IMAGES . $this->_goalFolder . $newFileName;
  	switch ($this->_imageType) {
      case 'jpg': return imagejpeg($image, $fullPath, $quality);
      case 'gif': return imagegif($image, $fullPath);
      case 'png': return imagepng($image, $fullPath);
      case 'bmp': return imagewbmp($image, $fullPath);
      default: return false;
    }
  }
  
  /**
   * Возвращает случайное имя
   *
   * @param integer $simbols
   * @return string
   */
  private function _generateName($simbols = 16) {
  	if (!empty($this->_goalName)) return $this->_goalName . '.' . $this->_imageType; 
  	do {
  		$name = substr(md5(time() . mt_rand(1, 999999)), 0, $simbols) . '.' . $this->_imageType;
  	} while (file_exists(IMAGES . $this->_goalFolder . $name ));
  	return $name;
  }
  
  /**
   * Возвращает случайное имя
   *
   * @param integer $simbols
   * @return string
   */
  private function _generateNameAfterPrefixes($simbols = 14) {
  	if (!empty($this->_goalName)) $this->_afterPrefixName = $this->_goalName . '.' . $this->_imageType;
  	else {
	  	$isAnyFileExists = false;
	  	do {
	  		$name = substr(md5(time() . mt_rand(1, 999999)), 0, $simbols) . '.' . $this->_imageType;
	  		foreach ($this->_arrSizes as $arrSize) {
	  			if (file_exists(IMAGES . $this->_goalFolder . $arrSize['prefix'] . $name )) $isAnyFileExists = true;
	  		}
	  	} while ($isAnyFileExists);
	  	$this->_afterPrefixName = $name;
  	}
  	return $this->_afterPrefixName;
  }
  
/**
   * Проверяет, загрузилась ли картинка
   *
   * @return bool
   */
  public function isLoaded() {
  	return $this->_isLoaded;
  }
}
?>